home *** CD-ROM | disk | FTP | other *** search
/ Mission 3 / Mission 3.zip / Mission 3.iso / texte / qed / src / file.c < prev    next >
C/C++ Source or Header  |  1998-11-09  |  15KB  |  752 lines

  1. #include <errno.h>
  2. #include <stat.h>
  3. #include <time.h>
  4. #include <unistd.h>
  5.  
  6. #include "global.h"
  7. #include "aktion.h"
  8. #include "comm.h"
  9. #include "edit.h"
  10. #include "find.h"
  11. #include "icon.h"
  12. #include "memory.h"
  13. #include "olga.h"
  14. #include "options.h"
  15. #include "projekt.h"
  16. #include "rsc.h"
  17. #include "text.h"
  18. #include "window.h"
  19. #include "file.h"
  20.  
  21.  
  22. static PATH    last_path;                         /* letzter Pfad der Dateiauswahl */
  23.  
  24. /* Puffer-Länge zum Lesen/Schreiben */
  25. #define    BUFFERSIZE    4*1024L
  26.  
  27. void open_error(char *filename, int error)
  28. {
  29.     FILENAME    datei;
  30.     PATH        path;
  31.  
  32.     split_filename(filename, path, datei);
  33.     if (error == -33 && path_exists(path))    /* file not found und Pfad existiert */
  34.         snote(1, 0, NOTEXIST, datei);
  35.     else
  36.         snote(1, 0, READERR, datei);
  37. }
  38.  
  39. int load(TEXTP t_ptr, bool verbose)
  40. {
  41.     int    antw;
  42.     bool    null_byte;
  43.     
  44.     antw = load_datei(t_ptr->filename, &t_ptr->text, verbose, &null_byte);
  45.     t_ptr->cursor_line = t_ptr->text.head.nachf;
  46.     t_ptr->readonly = file_readonly(t_ptr->filename);
  47.     if (null_byte)
  48.         t_ptr->moved++;
  49.     if (antw == 0)
  50.     {
  51.         t_ptr->file_date_time = file_time(t_ptr->filename,NULL,NULL);
  52.     }
  53.     else
  54.         t_ptr->file_date_time = -1L;
  55.     return(antw);
  56. }
  57.  
  58.  
  59. int load_datei(char *name, RINGP t, bool verbose, bool *null_byte)
  60. {
  61.     int    fd, antw;
  62.     long    filesize;
  63.     bool    nb = FALSE, 
  64.             ol = FALSE;
  65.     
  66.     /* größe der Datei ermitteln */
  67.     filesize = file_size(name);
  68.     if (filesize >= 0L)
  69.     {
  70.         fd = (int) Fopen(name, 0);
  71.         if (fd > 0)
  72.         {
  73.             char        *buffer, *zeile;
  74.             ZEILEP     start, next;
  75.             long        l, p, bytes;
  76.             int        n;
  77.             bool    new_line, cr = FALSE, mem = TRUE;
  78.  
  79.             /* Puffer anfordern */
  80.             buffer = (char *)malloc(BUFFERSIZE);
  81.             zeile = malloc(MAX_LINE_LEN + 2);                /* + 2 für Zeilenende */
  82.  
  83.             if (buffer == NULL || zeile == NULL)
  84.             {
  85.                 note(1, 0, NOMEMORY);
  86.                 return -39;
  87.             }                
  88.  
  89.             nb = FALSE;
  90.             graf_mouse(HOURGLASS, NULL);
  91.  
  92.             /* Progress-Bar */
  93.             verbose = verbose && ((filesize >> 10) >= transfer_size);
  94.             if (verbose)
  95.             {
  96.                 char        str[40];
  97.                 FILENAME    file;
  98.  
  99.                 strcpy(str, rsc_string(LOADSTR));
  100.                 file_name(name, file, FALSE);
  101.                 strcat(str, file);
  102.                 start_aktion(str, FALSE, filesize);
  103.                 bytes = 0L;
  104.             }
  105.  
  106.  
  107.             /* Liste vorbereiten */
  108.             start = t->tail.vorg;
  109.  
  110.             /* Einlesen */
  111.             l = Fread(fd, BUFFERSIZE, buffer);
  112.  
  113.             n = 0;
  114.             new_line = FALSE;
  115.             while (mem && (l > 0))
  116.             {
  117.                 p = 0;
  118.                 while (mem && (p < l))
  119.                 {
  120.                     if (t->ending != binmode)
  121.                     {
  122.                         if (buffer[p] == 0x0D)                /* CR -> Mac */
  123.                         {
  124.                             new_line = TRUE;
  125.                             p++;
  126.                             cr = TRUE;
  127.                             t->ending = apple;
  128.                         }
  129.                         else if (buffer[p] == 0x0A)        /* LF */
  130.                         {
  131.                             p++;
  132.                             if (cr)                                /* CRLF -> TOS*/
  133.                             {
  134.                                 cr = FALSE;
  135.                                 t->ending = tos;
  136.                             }
  137.                             else
  138.                             {
  139.                                 new_line = TRUE;                /* -> Unix */
  140.                                 t->ending = unix;
  141.                             }
  142.                         }
  143.                         else if (n >= t->max_line_len)    /* Überlänge */
  144.                         {
  145.                             ol = TRUE;
  146.                             new_line = TRUE;
  147.                         }
  148.                         else 
  149.                         {
  150.                             /* Nullbyte? */
  151.                             if (buffer[p] == '\0')
  152.                             {
  153.                                 nb = TRUE;
  154.                                 buffer[p] = ' ';                /* Durch Leerzeichen ersetzen */
  155.                             }
  156.                             zeile[n] = buffer[p];
  157.                             n++;
  158.                             p++;
  159.                         }
  160.                     }
  161.                     else    /* binmode */
  162.                     {
  163.                         if (n >= (t->max_line_len - 1))
  164.                             new_line = TRUE;
  165.                         zeile[n] = buffer[p];
  166.                         n++;
  167.                         p++;
  168.                     }
  169.                     
  170.                     if (new_line)
  171.                     {
  172.                         zeile[n] = EOS;
  173.                         start->nachf = new_col(zeile, n);
  174.                         if (start->nachf == NULL)
  175.                             mem = FALSE;
  176.                         else
  177.                         {
  178.                             start = start->nachf;
  179.                             if (ol)
  180.                             {
  181.                                 start->info |= OVERLEN;
  182.                                 ol = FALSE;
  183.                             }
  184.                         }
  185.                         n = 0;
  186.                         new_line = FALSE;
  187.                     }
  188.                 } /* while */
  189.  
  190.                 if (verbose)
  191.                 {
  192.                     bytes += BUFFERSIZE;
  193.                     do_aktion("", bytes);
  194.                 }
  195.                 l = Fread(fd, BUFFERSIZE, buffer);
  196.  
  197.                 /* EOF */
  198.                 if (l == 0)
  199.                 {
  200.                     /* letzte Zeile ohne Zeilenende! */
  201.                     if (n > 0)
  202.                     {
  203.                         zeile[n] = EOS;
  204.                         start->nachf = new_col(zeile, n);
  205.                         if (start->nachf == NULL)
  206.                             mem = FALSE;
  207.                         else
  208.                             start = start->nachf;
  209.                     }
  210.  
  211.                     /* letzte Zeile hatte ZE -> ein Dummyzeile anhängen */
  212.                     else if (n == 0)
  213.                     {
  214.                         start->nachf = new_col(zeile, 0);
  215.                         if (start->nachf == NULL)
  216.                             mem = FALSE;
  217.                         else
  218.                             start = start->nachf;
  219.                     }
  220.                 }
  221.             } /* while */
  222.  
  223.             if (mem)
  224.             {
  225.                 /* Ring schließen */
  226.                 t->tail.vorg = start;
  227.                 start->nachf = &t->tail;
  228.     
  229.                 /* Anzahl der Zeilen ermitteln */
  230.                 start = t->head.nachf;
  231.                 next = start->nachf;
  232.                 for (l = 0; !IS_TAIL(start); l++)
  233.                 {
  234.                     next->vorg = start;
  235.                     start = next;
  236.                     NEXT(next);
  237.                 }
  238.                 t->lines = l;
  239.                 if (l > 1L)
  240.                     col_delete(t, t->head.nachf);
  241.  
  242.                 antw = 0;
  243.             }
  244.             else
  245.             {
  246.                 /* Speichermangel! Bisher gelesene Zeilen freigeben. */
  247.                 next = FIRST(t);
  248.                 while (next)
  249.                 {
  250.                     start = next;
  251.                     NEXT(next);
  252.                     free_col(start);
  253.                 }
  254.                 graf_mouse(ARROW, NULL);
  255.                 note(1, 0, NOMEMORY);
  256.                 antw = -39;
  257.             }
  258.             Fclose(fd);
  259.  
  260.             free(buffer);
  261.             free(zeile);
  262.             
  263.             if (verbose)
  264.                 end_aktion();
  265.  
  266.             graf_mouse(ARROW, NULL);
  267.         }
  268.         else
  269.             antw = fd;
  270.     }
  271.     else
  272.         antw = -1;
  273.     if (null_byte != NULL)
  274.         *null_byte = nb;
  275.     return(antw);
  276. }
  277.  
  278.  
  279. /*
  280.  * Ermittelt die anzahl der Bytes und Zeilen der übergebenen Datei.
  281.  * Wird bei der Projektverwaltung (Info) benutzt.
  282.  */
  283. int infoload(char *name, long *bytes, long *lines)
  284. {
  285.     RING    t;
  286.     int    antw = 1;
  287.  
  288.     if (file_exists(name))
  289.     {
  290.         init_textring(&t);
  291.         if (load_datei(name, &t, FALSE, NULL) == 0)
  292.         {
  293.             *bytes = textring_bytes(&t);
  294.             *lines = t.lines;
  295.             antw = 0;
  296.         }
  297.         kill_textring(&t);
  298.     }
  299.     else
  300.     {
  301.         char    s[28];
  302.         
  303.         *bytes = 0;
  304.         *lines = 0;
  305.         make_shortpath(name, s, 28);
  306.         snote(1, 0, READERR, s);
  307.     }
  308.     return antw;
  309. }
  310.  
  311.  
  312. /****************************************************************************/
  313.  
  314. long    void backup_name(char *name, char *ext)
  315. {
  316.     PATH        new;
  317.     FILENAME    new_name;
  318.     
  319.     strcpy(new, name);
  320.     strcat(new, ".");
  321.     strcat(new, ext);
  322.     file_name(new, new_name, FALSE);
  323.     if (fs_long_name(new) >= strlen(new_name))
  324.         strcpy(name, new);
  325.     else
  326.         set_extension(name, ext);
  327. }
  328.  
  329. static void restore_back_up(TEXTP t_ptr)
  330. {
  331.     if (t_ptr->loc_opt->backup)
  332.     {
  333.         PATH old;
  334.  
  335.         if (file_exists(t_ptr->filename))
  336.             Fdelete(t_ptr->filename);
  337.         strcpy(old, t_ptr->filename);
  338.         backup_name(old, t_ptr->loc_opt->backup_ext);
  339.         Frename(0, old, t_ptr->filename);
  340.     }
  341. }
  342.  
  343.  
  344. static void back_up(TEXTP t_ptr)
  345. {
  346.     PATH new;
  347.  
  348.     if (t_ptr->loc_opt->backup)
  349.     {
  350.         graf_mouse(HOURGLASS, NULL);
  351.         strcpy(new, t_ptr->filename);
  352.         backup_name(new, t_ptr->loc_opt->backup_ext);
  353.         if (file_exists(new))            /* Alte DUP-Datei löschen */
  354.             Fdelete(new);
  355.         Frename(0, t_ptr->filename, new);
  356.         graf_mouse(ARROW, NULL);
  357.     }
  358. }
  359.  
  360. int save_datei(char *name, RINGP t, bool verbose)
  361. {
  362.     int    fd, antw;
  363.  
  364.     fd = (int) Fcreate(name, 0);
  365.     if (fd > 0)
  366.     {
  367.         char        end_str[3], *zeile, *buffer, *ptr;
  368.         int        e_len, z_len;
  369.         long        ret, count, b, rest, text_size;
  370.         ZEILEP    lauf;
  371.  
  372.         /* Puffer anfordern */
  373.         buffer = (char *)malloc(BUFFERSIZE);
  374.         zeile = (char *)malloc(MAX_LINE_LEN + 2);
  375.  
  376.         if (buffer == NULL || zeile == NULL)
  377.         {
  378.             note(1, 0, NOMEMORY);
  379.             return -39;
  380.         }                
  381.  
  382.         graf_mouse(HOURGLASS, NULL);
  383.  
  384.         /* Progress-Bar */
  385.         text_size = textring_bytes(t);
  386.         verbose = verbose && ((text_size >> 10) >= transfer_size);
  387.         if (verbose)
  388.         {
  389.             char    str[40];
  390.             FILENAME    file;
  391.  
  392.             strcpy(str, rsc_string(SAVESTR));
  393.             file_name(name, file, FALSE);
  394.             strcat(str,file);
  395.             start_aktion(str, FALSE, text_size);
  396.             count = 0L;
  397.         }
  398.  
  399.         /* String mit Zeilenende erzeugen */
  400.         switch (t->ending)
  401.         {
  402.             case tos :
  403.                 strcpy(end_str, "\r\n");
  404.                 e_len = 2;
  405.                 break;
  406.             case unix :
  407.                 strcpy(end_str, "\n");
  408.                 e_len = 1;
  409.                 break;
  410.             case apple :
  411.                 strcpy(end_str, "\r");
  412.                 e_len = 1;
  413.                 break;
  414.             default:
  415.                 strcpy(end_str, "");
  416.                 e_len = 0;
  417.                 break;
  418.         }
  419.         
  420.         lauf = FIRST(t);
  421.         if (lauf != NULL)
  422.         {
  423.             b = 0L;
  424.             ret = 1;
  425.             ptr = buffer;
  426.             rest = BUFFERSIZE;
  427.             while ((!IS_TAIL(lauf)) && (ret > 0))
  428.             {
  429.                 /* Zeile aus Text und Zeilenende zusammen setzen */
  430.                 memcpy(zeile, TEXT(lauf), lauf->len);
  431.                 z_len = lauf->len;
  432.  
  433.                 /*
  434.                  * Das Zeilenende wird nur dann angehängt, wenn lauf nicht letzte
  435.                  * Zeile ist. Gab es beim Laden der Datei in der letzten Zeile
  436.                  * ein ZE, gibt es die Dummyzeile. Gab es das ZE nicht, wird auch
  437.                  * kein ZE angehängt!
  438.                  */
  439.                 if (!IS_LAST(lauf) && (e_len > 0) && !IS_OVERLEN(lauf))
  440.                 {
  441.                     memcpy(zeile + lauf->len, end_str, e_len);
  442.                     z_len += e_len;
  443.                 }
  444.                 
  445.                 /* Passt die Zeile noch in den Puffer? */
  446.                 if (z_len < rest)
  447.                 {
  448.                     /* komplett in den Puffer */
  449.                     memcpy(ptr, zeile, z_len);
  450.                     ptr += z_len;
  451.                     b += z_len;
  452.                     rest -= z_len;
  453.                 }
  454.                 else
  455.                 {
  456.                     /* nur soviel kopieren, wie noch passt */
  457.                     memcpy(ptr, zeile, rest);
  458.                     ptr += rest;
  459.                     
  460.                     /* wegschreiben */
  461.                     ret = Fwrite(fd, BUFFERSIZE, buffer);
  462.                     if (verbose)
  463.                     {
  464.                         count += BUFFERSIZE;
  465.                         do_aktion("", count);
  466.                     }
  467.  
  468.                     if (ret != BUFFERSIZE)
  469.                         ret = -ENOSPC;
  470.  
  471.                     /* und den Rest in den Puffer */
  472.                     b = z_len - rest;
  473.                     ptr = buffer;
  474.                     memcpy(ptr, zeile + rest, b);
  475.                     ptr += b;
  476.                     
  477.                     rest = BUFFERSIZE - b;
  478.                 }
  479.                 NEXT(lauf);
  480.             }
  481.  
  482.             /* Befindet sich noch etwas im Puffer und ist kein Fehler aufgetreten? */
  483.             if ((b > 0L) && (ret > 0))
  484.             {
  485.                 ret = Fwrite(fd, b, buffer);
  486.                 if (verbose)
  487.                 {
  488.                     count += b;
  489.                     do_aktion("", count);
  490.                 }
  491.                 if (ret != b)
  492.                     ret = -ENOSPC;
  493.             }
  494.             if (ret < 0)
  495.                 antw = (int)ret;
  496.             else
  497.                 antw = 0;
  498.         }
  499.         else
  500.             antw = 1;
  501.  
  502.         Fclose(fd);
  503.         if (antw == -ENOSPC)
  504.             Fdelete(name);
  505.  
  506.         free(buffer);
  507.         free(zeile);
  508.  
  509.         if (verbose)
  510.             end_aktion();
  511.     }
  512.     else
  513.         antw = fd;
  514.  
  515.     graf_mouse(ARROW, NULL);
  516.     return antw;
  517. }
  518.  
  519.  
  520. int save(TEXTP t_ptr)
  521. {
  522.     int            antw;
  523.     struct stat    st;
  524.  
  525.     if (file_exists(t_ptr->filename))
  526.     {
  527.         if (file_readonly(t_ptr->filename))
  528.         {
  529.             FILENAME    file;
  530.  
  531.             t_ptr->readonly = TRUE;
  532.             file_name(t_ptr->filename, file, FALSE);
  533.             snote(1, 0, READONLY, file);
  534.             return -39;
  535.         }
  536.         else
  537.             t_ptr->readonly = FALSE;
  538.         if (t_ptr->file_date_time != -1L)
  539.         {
  540.             long date_time = file_time(t_ptr->filename, NULL, NULL);
  541.  
  542.             if (date_time != t_ptr->file_date_time)
  543.             {
  544.                 FILENAME    name;
  545.  
  546.                 file_name(t_ptr->filename, name, FALSE);
  547.                 if (snote(1, 2, MOVED2, name) == 2)
  548.                     return -1;
  549.             }
  550.         }
  551.     }
  552.     stat(t_ptr->filename, &st);
  553.     back_up(t_ptr);
  554.     antw = save_datei(t_ptr->filename, &t_ptr->text, TRUE);
  555.     if (antw == 0)
  556.     {
  557.         t_ptr->moved = 0;
  558.         t_ptr->file_date_time = file_time(t_ptr->filename, NULL, NULL);
  559.         t_ptr->asave = time(NULL);
  560.  
  561.         /* OLGA informieren */
  562.         do_olga(OLGA_UPDATE, t_ptr->filename, NULL);
  563.  
  564.         /* Attribute wieder herstellen */
  565.         chmod(t_ptr->filename, (st.st_mode & 0x0000FFFF));
  566.         if (getuid() == 0)                        /* nur root darf Owner ändern */
  567.             chown(t_ptr->filename, st.st_uid, st.st_gid);
  568.     }
  569.     else
  570.     {
  571.         if (antw == -ENOSPC)
  572.         {
  573.             char    tmp[20];
  574.  
  575.             make_shortpath(t_ptr->filename, tmp, 19);
  576.             snote(1, 0, NOSPACE, tmp);
  577.         }
  578.         else
  579.             note(1, 0, WRITEERR);
  580. /*        restore_back_up(t_ptr); */
  581.         t_ptr->file_date_time = -1L;
  582.     }
  583.  
  584.     return antw;
  585. }
  586.  
  587.  
  588. int save_as(TEXTP t_ptr, char *name)
  589. {
  590.     int    antw;
  591.  
  592.     if (file_exists(name))
  593.     {
  594.         if (file_readonly(name))
  595.         {
  596.             FILENAME    file;
  597.  
  598.             file_name(t_ptr->filename, file, FALSE);
  599.             snote(1, 0, READONLY, file);
  600.             return -39;
  601.         }
  602.     }
  603.     antw = save_datei(name, &t_ptr->text, TRUE);
  604.     if (antw != 0)
  605.     {
  606.         if (antw == -ENOSPC)
  607.         {
  608.             char    tmp[20];
  609.  
  610.             make_shortpath(t_ptr->filename, tmp, 19);
  611.             snote(1, 0, NOSPACE, tmp);
  612.         }
  613.         else
  614.             note(1, 0, WRITEERR);
  615. /*        restore_back_up(t_ptr);*/
  616.     }
  617.     return(antw);
  618. }
  619.  
  620.  
  621. bool    save_new(char *name, char *mask, char *title)
  622. {
  623.     PATH    new;
  624.     bool    ok = FALSE;
  625.     
  626.     if ((name[0] == EOS) || (strcmp(name, rsc_string(NAMENLOS)) == 0))
  627.         strcpy(new, last_path);
  628.     else
  629.         strcpy(new, name);
  630.     if (select_single(new, mask, title))
  631.     {
  632.         if (strcmp(name, new) != 0)        /* wirklich neuer Name? */
  633.         {
  634.             if (file_exists(new) && (note(1, 2, EXIST) == 2))
  635.                 ok = FALSE;
  636.             else
  637.             {
  638.                 strcpy(name, new);
  639.                 ok = TRUE;
  640.             }
  641.         }
  642.         else
  643.             ok = FALSE;
  644.     }
  645.     return ok;
  646. }
  647.  
  648.  
  649. /*****************************************************************************/
  650. /* Dateiauswahl                                                                                  */
  651. /*****************************************************************************/
  652. static bool    multi_bin = FALSE;
  653.  
  654. void store_path(char *path)
  655. {
  656.     PATH    p;
  657.  
  658.     split_filename(path, p, NULL);
  659.     if (strcmp(last_path, p) != 0)        /* neuer Pfad? */
  660.     {
  661.         if (path_exists(p))
  662.             strcpy(last_path, p);
  663.     }
  664. }
  665.  
  666. bool select_single(char *filename, char *mask, char *title)
  667. {
  668.     PATH        path = "";
  669.     FILENAME    name = "";
  670.     bool        ok;
  671.     
  672.     if (filename[0] != EOS)
  673.         split_filename(filename, path, name);
  674.     else
  675.         strcpy(path, last_path);
  676.  
  677.     ok = select_file(path, name, mask, title, FSCB_NULL);
  678.     if (ok && name[0] != EOS)            /* für den Fall, daß nur ein Verzeichnis kommt */
  679.     {
  680.         strcpy(filename, path);
  681.         strcat(filename, name);
  682.         store_path(path);
  683.     }
  684.     return ok;
  685. }
  686.  
  687.  
  688. bool select_path(char *pathname, char *title)
  689. {
  690.     PATH        path = "";
  691.     FILENAME    name = "";
  692.     bool        ok;
  693.     
  694.     if (pathname[0] != EOS)
  695.         split_filename(pathname, path, NULL);
  696.     else
  697.         strcpy(path, last_path);
  698.  
  699.     ok = select_file(path, name, "", title, FSCB_NULL);
  700.     if (ok)                            /* für den Fall, daß nur ein Verzeichnis kommt */
  701.     {
  702.         strcpy(pathname, path);
  703.         store_path(path);
  704.     }
  705.     return ok;
  706. }
  707.  
  708. static int open_multi(char *path, char *name)
  709. {
  710.     if (name[0] != EOS)            /* für den Fall, daß nur ein Verzeichnis kommt */
  711.     {
  712.         PATH    filename;
  713.         int    r;
  714.         
  715.         strcpy(filename, path);
  716.         strcat(filename, name);
  717.         if (!shift_pressed() && filematch(filename, "*.QPJ", -1))
  718.             r = load_projekt(filename);
  719.         else
  720.             r = load_edit(filename, multi_bin);
  721.         if (r > 0)
  722.             send_dhst(filename);
  723.     }
  724.     return TRUE;
  725. }
  726.  
  727. void select_multi(bool binary)
  728. {
  729.     PATH        path;
  730.     FILENAME    name = "";
  731.     char        *title;
  732.  
  733.     multi_bin = binary;
  734.     strcpy(path, last_path);
  735.  
  736.     if (binary)
  737.         title = rsc_string(LOADBINSTR);
  738.     else
  739.         title = rsc_string(LOADFILESTR);
  740.     select_file(path, name, "", title, open_multi);
  741. }
  742.  
  743. /******************************************************************************/
  744. void init_file(void)
  745. {
  746.     get_path(last_path, 0);                            /* Aktuellen Pfad holen */
  747. }
  748.  
  749. void term_file(void)
  750. {
  751. }
  752.